/**
 * \brief  Implementation of Thread API interface ontop of Platform_thread
 * \author Norman Feske
 * \date   2006-05-03
 */

/*
 * Copyright (C) 2006-2009 Norman Feske
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

/* Genode */
#include <base/thread.h>
#include <base/printf.h>
#include <base/sleep.h>

/* Core */
#include "platform.h"
#include "core_env.h"

using namespace Genode;

/* DEBUGGING */
static bool verbose = false;

/**
 * Thread-startup argument frame
 */
Thread_base *Thread_base::_startup_arg;
Lock         Thread_base::_startup_arg_lock;


void Thread_base::_thread_start(void *arg)
{
	/* read and release thread-argument frame */
	Thread_base *me = Thread_base::_startup_arg;
	Thread_base::_startup_arg_lock.unlock();

	if (verbose)
		PDBG("starting new thread at 0x%p", me);

	me->entry();

	if (verbose)
		PDBG("returned from entry function... sleeping...");

	sleep_forever();
}


void Thread_base::_start(void *sp, const char *name)
{
	/* push this-pointer to the stack of the new thread */
	void **stack = reinterpret_cast<void **>(sp);
	stack[0] = this;

	/* create and start platform thread */
	_tid.pt = new(platform()->ram_alloc()) Platform_thread(name);
	Platform *p = dynamic_cast<Platform *>(platform());

	p->core_pd()->bind_thread(_tid.pt);
	_tid.pt->pager_cap(Thread_capability(Capability(p->core_pager()->l4_thread_id(), 0)));
	_tid.l4id = _tid.pt->l4_thread_id();

	/* pass thread argument via startup-argument frame to new thread */
	_startup_arg_lock.lock();
	_startup_arg = this;

	_tid.pt->start((void *)_thread_start, &stack[-1]);
}


void Thread_base::cancel_blocking()
{
	/*
	 * Within Core, we never need to unblock threads
	 */
}


Thread_base::~Thread_base()
{
	/* destruct platform thread */
	destroy(platform()->ram_alloc(), _tid.pt);
}
